package algebra.algorithms;

import accessstruct.Tool;
import it.unisa.dia.gas.jpbc.Element;
import it.unisa.dia.gas.jpbc.Pairing;
import it.unisa.dia.gas.plaf.jpbc.pairing.PairingFactory;
import scheme.CSP;
import scheme.LWPPMAABE;
import util.ConfigFileName;

import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @Classname AttrTrans
 * @Description 属性盲化类
 * @Date
 * @Created by kevin
 */
public class AttrTrans {
    /**
     *
     * @param config 配置文件
     * @param userId 用户id 用于生成H（uid）
     * @param userAttList 用户属性列表
     * @param aid AA的编号
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static LWPPMAABE.Pair<Element[],Long> AttrTrans(ConfigFileName config , String userId, String[] userAttList, int aid) throws NoSuchAlgorithmException {
        /**************************************************************************************************************/
        //准备工作获取公参
        Pairing bp = PairingFactory.getPairing(config.getPairingParametersFileName());
        Properties AApkProp = Tool.loadPropFromFile(config.getAAPKFileName());

        //获取属性转换密钥
        String ATKgtauString = AApkProp.getProperty("g_tau-"+aid);//
        Element ATK_g_tau = bp.getG1().newElementFromBytes(Base64.getDecoder().decode(ATKgtauString)).getImmutable();//
        String ATKphiString = AApkProp.getProperty("phi-"+aid);//
        Element ATK_phi = bp.getZr().newElementFromBytes(Base64.getDecoder().decode(ATKphiString)).getImmutable();//

        /************************************************开始计算********************************************************/
        long startTime = System.currentTimeMillis();
        //依次对各个属性进行转换
        Element[] TransAttrList= new Element[userAttList.length];
        for(int i = 0;i<userAttList.length;i++){

            byte[] attHash = Tool.sha1(userAttList[i]);//
            Element H_x = bp.getG1().newElementFromHash(attHash, 0, attHash.length).getImmutable();//

            TransAttrList[i] = bp.pairing(ATK_g_tau.powZn(ATK_phi),H_x).getImmutable();;//
        }
        //对userId进行hash操作
        byte[] userIdHash = Tool.sha1(userId);
        Element H_uid = bp.getG1().newElementFromHash(userIdHash, 0, userIdHash.length).getImmutable();//

        long endTime = System.currentTimeMillis();
        //新属性存放在TransAttrList[i]中 ，以为就是S‘aid uid要进行存储，
        CSP.saveUserTransAtt(H_uid,TransAttrList);
        return  new LWPPMAABE.Pair(TransAttrList,endTime - startTime);
    }
    /**
     * 属性盲化算法生成访问策略时使用不需要用户uid
     * @param config
     * @param userAttList 主要是这个int
     * @param aid
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static Element localAttrTrans(ConfigFileName config,String userAttList,int aid) throws NoSuchAlgorithmException {
        /*************************************************获取公共参数****************************************************/
        //准备工作获取公参
        Pairing bp = PairingFactory.getPairing(config.getPairingParametersFileName());
        Properties AApkProp = Tool.loadPropFromFile(config.getAAPKFileName());
        Properties GPProp = Tool.loadPropFromFile(config.getGPFileName());
        //获取属性转换密钥
        String ATKgtauString = AApkProp.getProperty("g_tau_"+aid);
        Element ATK_g_tau = bp.getG1().newElementFromBytes(Base64.getDecoder().decode(ATKgtauString)).getImmutable();
        String ATKphiString = AApkProp.getProperty("phi_"+aid);
        Element ATK_phi = bp.getG1().newElementFromBytes(Base64.getDecoder().decode(ATKphiString)).getImmutable();

        /*************************************************开始转化******************************************************/
        long startTime = System.currentTimeMillis();
        byte[] attHash = Tool.sha1(userAttList);
        Element H_x = bp.getG1().newElementFromHash(attHash, 0, attHash.length).getImmutable();
//        Element H_x = bp.getG1().newElementFromBytes(userAttList.getBytes());
        Element TransedAtt  = bp.pairing(ATK_g_tau.powZn(ATK_phi),H_x).getImmutable();
        long endTime = System.currentTimeMillis();
        //新属性存放在TransAttrList[i]中 ，以为就是S‘aid uid要进行存储，
        return TransedAtt;
    }

    /**
     * 替换访问策略里的rhos
     * @param lambdas
     * @return rho_lambda
     * @throws NoSuchAlgorithmException
     */
    public static Map<String, Element> replaceRhos(ConfigFileName config,Map<String, Element> lambdas,String[] AccessAtt,int aaNums) throws NoSuchAlgorithmException {
        /**************************************************************************************************************/
        Map<String, Element> rho_lambda = new HashMap<String, Element>();
        int totalLen = AccessAtt.length;
        int aveLen = totalLen/aaNums;
        for(int aid = 1; aid <= aaNums;aid++){
            String[] AAiAttL = new String[aveLen];
            for(int j = 0;j<aveLen;j++){
                if(lambdas.containsKey(AccessAtt[(aid-1)*aveLen + j]))
                {
                    Element transedRho = localAttrTrans(config,AccessAtt[(aid-1)*aveLen + j],aid).getImmutable();;
                    rho_lambda.put(AccessAtt[(aid-1)*aveLen + j],transedRho);
                }
            }
        }
        return rho_lambda;
    }
}
